home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS02.ADF / IFF / ilbmw.c < prev    next >
Text File  |  1989-05-30  |  5KB  |  143 lines

  1. /*----------------------------------------------------------------------*
  2.  * ILBMW.C  Support routines for writing ILBM files.           11/15/85
  3.  * (IFF is Interchange Format File.)
  4.  *
  5.  * By Jerry Morrison and Steve Shaw, Electronic Arts.
  6.  * This software is in the public domain.
  7.  *
  8.  * This version for the Commodore-Amiga computer.
  9.  *----------------------------------------------------------------------*/
  10. #include "iff/packer.h"
  11. #include "iff/ilbm.h"
  12.  
  13. /*---------- InitBMHdr -------------------------------------------------*/
  14. IFFP InitBMHdr(bmHdr0, bitmap, masking, compression, transparentColor,
  15.         pageWidth, pageHeight)
  16.         BitMapHeader *bmHdr0;  struct BitMap *bitmap;
  17.         int masking, compression, transparentColor, pageWidth, pageHeight;
  18.         /*  Masking, Compression, UWORD,            WORD,      WORD  */
  19.     {
  20.     register BitMapHeader *bmHdr = bmHdr0;
  21.     register WORD rowBytes = bitmap->BytesPerRow;
  22.  
  23.     bmHdr->w = rowBytes << 3;
  24.     bmHdr->h = bitmap->Rows;
  25.     bmHdr->x = bmHdr->y = 0;    /* Default position is (0,0).*/
  26.     bmHdr->nPlanes = bitmap->Depth;
  27.     bmHdr->masking = masking;
  28.     bmHdr->compression = compression;
  29.     bmHdr->pad1 = 0;
  30.     bmHdr->transparentColor = transparentColor;
  31.     bmHdr->xAspect = bmHdr->yAspect = 1;
  32.     bmHdr->pageWidth = pageWidth;
  33.     bmHdr->pageHeight = pageHeight;
  34.  
  35.     if (pageWidth = 320)
  36.     switch (pageHeight) {
  37.         case 200: {bmHdr->xAspect = x320x200Aspect;
  38.                bmHdr->yAspect = y320x200Aspect; break;}
  39.         case 400: {bmHdr->xAspect = x320x400Aspect;
  40.                bmHdr->yAspect = y320x400Aspect; break;}
  41.         }
  42.     else if (pageWidth = 640)
  43.     switch (pageHeight) {
  44.         case 200: {bmHdr->xAspect = x640x200Aspect;
  45.                bmHdr->yAspect = y640x200Aspect; break;}
  46.         case 400: {bmHdr->xAspect = x640x400Aspect;
  47.                bmHdr->yAspect = y640x400Aspect; break;}
  48.         }
  49.  
  50.     return( IS_ODD(rowBytes) ? CLIENT_ERROR : IFF_OKAY );
  51.     }
  52.  
  53. /*---------- PutCMAP ---------------------------------------------------*/
  54. IFFP PutCMAP(context, colorMap, depth)   
  55.       GroupContext *context;  WORD *colorMap;  UBYTE depth;
  56.    {
  57.    register LONG nColorRegs;   
  58.    IFFP iffp;
  59.    ColorRegister colorReg;
  60.  
  61.    if (depth > MaxAmDepth)   depth = MaxAmDepth;
  62.    nColorRegs = 1 << depth;
  63.  
  64.    iffp = PutCkHdr(context, ID_CMAP, nColorRegs * sizeofColorRegister);
  65.    CheckIFFP();
  66.  
  67.    for ( ;  nColorRegs;  --nColorRegs)  {
  68.       colorReg.red   = ( *colorMap >> 4 ) & 0xf0;
  69.       colorReg.green = ( *colorMap      ) & 0xf0;
  70.       colorReg.blue  = ( *colorMap << 4 ) & 0xf0;
  71.       iffp = IFFWriteBytes(context, (BYTE *)&colorReg, sizeofColorRegister);
  72.       CheckIFFP();
  73.       ++colorMap;
  74.       }
  75.  
  76.    iffp = PutCkEnd(context);
  77.    return(iffp);
  78.    }
  79.  
  80. /*---------- PutBODY ---------------------------------------------------*/
  81. /* NOTE: This implementation could be a LOT faster if it used more of the
  82.  * supplied buffer. It would make far fewer calls to IFFWriteBytes (and
  83.  * therefore to DOS Write). */
  84. IFFP PutBODY(context, bitmap, mask, bmHdr, buffer, bufsize)
  85.       GroupContext *context;  struct BitMap *bitmap;  BYTE *mask;
  86.       BitMapHeader *bmHdr;  BYTE *buffer;  LONG bufsize;
  87.    {         
  88.    IFFP iffp;
  89.    LONG rowBytes = bitmap->BytesPerRow;
  90.    int dstDepth = bmHdr->nPlanes;
  91.    Compression compression = bmHdr->compression;
  92.    int planeCnt;        /* number of bit planes including mask */
  93.    register int iPlane, iRow;
  94.    register LONG packedRowBytes;
  95.    BYTE *buf;
  96.    BYTE *planes[MaxAmDepth + 1]; /* array of ptrs to planes & mask */
  97.  
  98.    if ( bufsize < MaxPackedSize(rowBytes)  ||    /* Must buffer a comprsd row*/
  99.         compression > cmpByteRun1  ||        /* bad arg */
  100.     bitmap->Rows != bmHdr->h   ||        /* inconsistent */
  101.     rowBytes != RowBytes(bmHdr->w)  ||    /* inconsistent*/
  102.     bitmap->Depth < dstDepth   ||        /* inconsistent */
  103.     dstDepth > MaxAmDepth )            /* too many for this routine*/
  104.       return(CLIENT_ERROR);
  105.  
  106.    planeCnt = dstDepth + (mask == NULL ? 0 : 1);
  107.  
  108.    /* Copy the ptrs to bit & mask planes into local array "planes" */
  109.    for (iPlane = 0; iPlane < dstDepth; iPlane++)
  110.       planes[iPlane] = (BYTE *)bitmap->Planes[iPlane];
  111.    if (mask != NULL)
  112.       planes[dstDepth] = mask;
  113.  
  114.    /* Write out a BODY chunk header */
  115.    iffp = PutCkHdr(context, ID_BODY, szNotYetKnown);
  116.    CheckIFFP();
  117.  
  118.    /* Write out the BODY contents */
  119.    for (iRow = bmHdr->h; iRow > 0; iRow--)  {
  120.       for (iPlane = 0; iPlane < planeCnt; iPlane++)  {
  121.  
  122.          /* Write next row.*/
  123.          if (compression == cmpNone) {
  124.             iffp = IFFWriteBytes(context, planes[iPlane], rowBytes);
  125.             planes[iPlane] += rowBytes;
  126.             }
  127.  
  128.          /* Compress and write next row.*/
  129.          else {
  130.             buf = buffer;
  131.             packedRowBytes = PackRow(&planes[iPlane], &buf, rowBytes);
  132.             iffp = IFFWriteBytes(context, buffer, packedRowBytes);
  133.             }
  134.  
  135.          CheckIFFP();
  136.          }
  137.       }
  138.  
  139.    /* Finish the chunk */
  140.    iffp = PutCkEnd(context);
  141.    return(iffp);
  142.    }
  143.